package com.demo2.todo.service.impl;

import com.demo2.todo.model.dto.TodoRequest;
import com.demo2.todo.model.dto.TodoResponse;
import com.demo2.todo.exception.ResourceNotFoundException;
import com.demo2.todo.model.entity.Tag;
import com.demo2.todo.model.entity.Todo;
import com.demo2.todo.model.enums.ReviewStatus;
import com.demo2.todo.model.enums.TodoStatus;
import com.demo2.todo.model.entity.User;
import com.demo2.todo.repository.*;
import com.demo2.todo.service.TodoService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author evi
 */
@Service
@RequiredArgsConstructor
public class TodoServiceImpl implements TodoService {
    private final TodoRepository todoRepository;
    private final UserRepository userRepository;
    private final TagRepository tagRepository;
    private final ReportRepository reportRepository;
    private final CommentRepository commentRepository;

    @Override
    @Transactional(readOnly = true)
    public List<TodoResponse> getAllTodos(User user) {
        return todoRepository.findByUserOrderByCreatedAtDesc(user)
                .stream()
                .map(this::mapToDto)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(readOnly = true)
    public TodoResponse getTodoById(Long id, User user) {
        Todo todo = todoRepository.findByIdAndUser(id, user)
                .orElseThrow(() -> new ResourceNotFoundException("Todo not found"));
        return mapToDto(todo);
    }

    @Override
    @Transactional
    public List<TodoResponse> getTodosByUserId(Long userId) {
        // 先校验用户是否存在
//        User user = userRepository.findById(userId)
//                .orElseThrow(() -> new ResourceNotFoundException("用户不存在，ID: " + userId));

        // 查询该用户的所有待办
        return todoRepository.findByUserIdOrderByCreatedAtDesc(userId)
                .stream()
                .map(this::mapToDto)
                .collect(Collectors.toList());
    }


    @Override
    @Transactional
    public TodoResponse createTodo(TodoRequest request, User user) {
        Todo todo = new Todo();
        todo.setTitle(request.getTitle());
        todo.setContent(request.getContent());
        todo.setStatus(request.getStatus() != null ? request.getStatus() : TodoStatus.pending);
        todo.setUser(user);
        todo.setDeadline(request.getDeadline());

        // 保存并刷新实体，确保ID被正确生成
        Todo savedTodo = todoRepository.saveAndFlush(todo);
        Long todoId = savedTodo.getId();

        // 检查ID是否有效
        if (todoId == null) {
            throw new RuntimeException("Failed to generate Todo ID");
        }

        // 处理标签关联
        if (request.getTagIds() != null && !request.getTagIds().isEmpty()) {
            for (Long tagId : request.getTagIds()) {
                // 验证标签是否存在
                Tag tag = tagRepository.findByIdAndUserId(tagId, user.getId())
                        .orElseThrow(() -> new ResourceNotFoundException("标签不存在: " + tagId));
                // 插入关联关系
                tagRepository.insertTagRelation(todoId, tagId);
            }
        }

        return mapToDto(savedTodo);
    }


    @Override
    @Transactional
    public TodoResponse updateTodo(Long id, TodoRequest request, User user) {
        Todo todo = todoRepository.findByIdAndUser(id, user)
                .orElseThrow(() -> new ResourceNotFoundException("Todo not found"));
        if (request.getTitle() != null) {
            todo.setTitle(request.getTitle());
        }
        if (request.getContent() != null) {
            todo.setContent(request.getContent());
        }
        if (request.getStatus() != null) {
            todo.setStatus(request.getStatus());
        }
        if (request.getDeadline() != null) {
            todo.setDeadline(request.getDeadline());
        }
        // 处理标签：使用副本集合
        if (request.getTagIds() != null) {
            // 先删除所有关联
            tagRepository.deleteByTodoId(id);

            // 再添加新的关联
            for (Long tagId : request.getTagIds()) {
                Tag tag = tagRepository.findByIdAndUserId(tagId, user.getId())
                        .orElseThrow(() -> new ResourceNotFoundException("标签不存在: " + tagId));
                tagRepository.insertTagRelation(id, tagId);
            }
        }

        Todo updatedTodo = todoRepository.save(todo);
        return mapToDto(updatedTodo);
    }

    @Override
    @Transactional
    public void deleteTodo(Long id, User user) {
        // 1. 先删除关联的举报记录
        reportRepository.deleteByTodoId(id);

        // 2. 再删除待办事项与标签的关联关系
        tagRepository.deleteTagRelationsByTodoId(id);

//        commentRepository.deleteByUserId(user.getId());

        Todo todo = todoRepository.findByIdAndUser(id, user)
                .orElseThrow(() -> new ResourceNotFoundException("Todo not found"));
        todoRepository.delete(todo);
    }

    @Override
    @Transactional
    public List<TodoResponse> getAllTodosForAdmin() {
        return todoRepository.findAllByOrderByCreatedAtDesc()
                .stream()
                .map(this::mapToDto)
                .collect(Collectors.toList());
    }

    // 新增：切换待办事项状态
    @Transactional
    @Override
    public TodoResponse toggleStatus(Long id, String status, User user) {
        Todo todo = todoRepository.findByIdAndUser(id, user)
                .orElseThrow(() -> new ResourceNotFoundException("待办事项不存在"));

        todo.setStatus(TodoStatus.valueOf(status));
        Todo updatedTodo = todoRepository.save(todo);
        return mapToDto(updatedTodo);
    }

    // 新增：创建分享令牌
    @Transactional
    @Override
    public String createShareToken(Long id, User user) {
        Todo todo = todoRepository.findByIdAndUser(id, user)
                .orElseThrow(() -> new ResourceNotFoundException("待办事项不存在"));

        // 生成唯一令牌
        String shareToken = UUID.randomUUID().toString();

        // 设置令牌和过期时间（例如7天）
        todo.setShareToken(shareToken);
        todo.setShareExpiresAt(LocalDateTime.now().plusDays(7));

        todoRepository.save(todo);
        return shareToken;
    }

    // 新增：通过分享令牌获取待办事项
    @Transactional(readOnly = true)
    @Override
    public TodoResponse getSharedTodoByToken(String token) {
        Todo todo = todoRepository.findByShareToken(token)
                .orElseThrow(() -> new ResourceNotFoundException("分享链接无效或已过期"));

        // 检查是否过期
        if (todo.getShareExpiresAt().isBefore(LocalDateTime.now())) {
            throw new ResourceNotFoundException("分享链接已过期");
        }

        return mapToDto(todo);
    }

    // 在TodoServiceImpl中添加
    @Transactional(readOnly = true)
    @Override
    public List<TodoResponse> getPublicTodos() {
        // 查询所有审核通过且状态为公开的待办事项
        return todoRepository.findByReviewStatus(ReviewStatus.approved)
                .stream()
                .map(this::mapToDto)
                .collect(Collectors.toList());
    }

    private TodoResponse mapToDto(Todo todo) {
        TodoResponse dto = new TodoResponse();
        dto.setId(todo.getId());
        dto.setTitle(todo.getTitle());
        dto.setContent(todo.getContent());
        dto.setStatus(todo.getStatus());
        dto.setCreatedAt(todo.getCreatedAt());
        dto.setDeadline(todo.getDeadline());
        dto.setReviewStatus(todo.getReviewStatus());

        // 处理标签：使用副本集合避免ConcurrentModificationException
        dto.setTagIds(new HashSet<>(tagRepository.findTagIdsByTodoId(todo.getId())));

        return dto;
    }


}